home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Util / conv / Acvt.lha / Acvt 1.07 / sources / cdsk_dcm.cpp < prev    next >
C/C++ Source or Header  |  1999-06-10  |  15KB  |  763 lines

  1. //    This program is free software; you can redistribute it and/or modify
  2. //    it under the terms of the GNU General Public License as published by
  3. //    the Free Software Foundation; either version 2 of the License, or
  4. //    any later version.
  5. //
  6. //    This program is distributed in the hope that it will be useful,
  7. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9. //    GNU General Public License for more details.
  10. //
  11. //    You should have received a copy of the GNU General Public License
  12. //    along with this program; if not, write to the Free Software
  13. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. //
  15.  
  16. #include "cdsk_dcm.h"
  17. #include "cfile.h"
  18. #include "cprefile.h"
  19. #include "autil.h"
  20.  
  21. //#define _DCM_DUMP_
  22.  
  23. #define DCM_CHANGE_BEGIN    0x41        //Change only start of sector  
  24. #define DCM_DOS_SECTOR      0x42        //128 byte compressed sector   
  25. #define DCM_COMPRESSED      0x43        //Uncompressed/compressed pairs
  26. #define DCM_CHANGE_END      0x44        //Change only end of sector    
  27. #define DCM_PASS_END            0x45        //End of pass
  28. #define DCM_SAME_AS_BEFORE  0x46        //Same as previous non-zero    
  29. #define DCM_UNCOMPRESSED    0x47        //Uncompressed sector          
  30.  
  31. #define DCM_HEADER_SINGLE    0xFA
  32. #define DCM_HEADER_MULTI    0xF9
  33.  
  34. #define DCM_DENSITY_SD        0            //Single density, 90K          
  35. #define DCM_DENSITY_DD        1            //Double density, 180K         
  36. #define DCM_DENSITY_ED        2            //Enhanced density, 130K       
  37.  
  38. CDcm::CDcm() : CDisk()
  39. {
  40.     #ifdef _MEMORY_DUMP_
  41.         printf( "CDcm constructed: %08X\n", this );
  42.     #endif
  43. }
  44.  
  45. CDcm::~CDcm()
  46. {
  47.     #ifdef _MEMORY_DUMP_
  48.         printf( "CDcm destructed: %08X\n", this );
  49.     #endif
  50. }
  51.  
  52. BOOL CDcm::Load( char* szFname, BOOL, BOOL )
  53. {
  54.     BYTE    btArcType = 0;        //Block type for first block
  55.     BYTE    btBlkType;        //Current block type
  56.  
  57.     m_bAlreadyFormatted = FALSE;
  58.     m_bLastPass = FALSE;
  59.     m_wCurrentSector = 0;
  60.  
  61.     CFile cfo;
  62.     CPreFile cf;
  63.  
  64.     if ( !cfo.Open( szFname ) )
  65.     {
  66.         sprintf( m_szLastError, "DCM: Can't open '%s'", szFname );
  67.         m_iErrorCode = CDISK_ERROR_CANT_OPEN;
  68.         return FALSE;
  69.     }
  70.  
  71.     strcpy( m_szFname, szFname );
  72.  
  73.     cf.Open( &cfo, 20 );
  74.  
  75.     m_lFileLength = cf.GetLength();
  76.  
  77.     for(;;) //outpass
  78.     {
  79.         if ( cf.Tell() >= m_lFileLength )
  80.         {
  81.             if ( ( !m_bLastPass ) && ( btArcType == DCM_HEADER_MULTI ) )
  82.             {
  83.                 sprintf( m_szLastError,"DCM: Multi-part archive error.\n" \
  84.                 "To process these files, you must first combine the files into a single file." );
  85.                 m_iErrorCode = CDCM_FORMAT_VIOLATED;
  86.                 return FALSE;
  87.             }
  88.         }
  89.  
  90.         btArcType = cf.readb();
  91.  
  92.         switch( btArcType )
  93.         {
  94.             case DCM_HEADER_MULTI:
  95.             case DCM_HEADER_SINGLE:
  96.                 if ( !DecodeRecFA( cf ) )
  97.                     return FALSE;
  98.                 break;
  99.  
  100.             default:
  101.                 sprintf( m_szLastError, "DCM: %02X is an unknown header block.\n", btArcType );
  102.                 return FALSE;
  103.         }
  104.  
  105.         for(;;) //inpass
  106.         {
  107.             btBlkType = cf.readb();
  108.  
  109.             if ( btBlkType == DCM_PASS_END )
  110.                 break;
  111.  
  112.             if ( cf.Tell() >= m_lFileLength )
  113.             {
  114.                 sprintf( m_szLastError, "DCM: EOF before end block." );
  115.                 m_iErrorCode = CDCM_FORMAT_VIOLATED;
  116.                 return FALSE;
  117.             }
  118.  
  119.             BOOL bRes = TRUE;
  120.  
  121.             *m_szLastError = '\0';
  122.             switch( btBlkType & 0x7F )
  123.             {
  124.                 case DCM_CHANGE_BEGIN:
  125.                     bRes = DecodeRec41( cf );
  126.                     break;
  127.  
  128.                 case DCM_DOS_SECTOR:
  129.                     bRes = DecodeRec42( cf );
  130.                     break;
  131.  
  132.                 case DCM_COMPRESSED:
  133.                     bRes = DecodeRec43( cf );
  134.                     break;
  135.  
  136.                 case DCM_CHANGE_END:
  137.                     bRes = DecodeRec44( cf );
  138.                     break;
  139.  
  140.                 case DCM_SAME_AS_BEFORE:
  141.                     //not needed
  142.                     //bRes = DecodeRec46( cf );
  143.                     break;
  144.  
  145.                 case DCM_UNCOMPRESSED:
  146.                     bRes = DecodeRec47( cf );
  147.                     break;
  148.  
  149.                 default:
  150.                 {
  151.                     switch( btBlkType )
  152.                     {
  153.                         case DCM_HEADER_MULTI:
  154.                         case DCM_HEADER_SINGLE:
  155.                             sprintf( m_szLastError, "DCM: Trying to start section but last section never had "
  156.                             "an end section block.");
  157.                             break;
  158.  
  159.                         default:
  160.                             sprintf( m_szLastError, "DCM: %02X is an unknown block type. File may be "
  161.                             "corrupt.",btBlkType);
  162.                             break;
  163.                     }
  164.  
  165.                     m_iErrorCode = CDCM_FORMAT_VIOLATED;
  166.                     return FALSE;
  167.                 }
  168.             }
  169.  
  170.             if ( !bRes )
  171.             {
  172.                 sprintf( m_szLastError, "DCM: Block %02X decode error!", btBlkType );
  173.                 m_iErrorCode = CDCM_FORMAT_VIOLATED;
  174.                 return FALSE;
  175.             }
  176.  
  177.             if ( !WriteSector( m_wCurrentSector, m_abtCurrBuff ) )
  178.                 return FALSE;
  179.  
  180.             if ( btBlkType & 0x80 )
  181.                 m_wCurrentSector++;
  182.             else
  183.                 m_wCurrentSector = cf.readLEw();
  184.  
  185.         } //infinite for (inpass)
  186.  
  187.         //End block
  188.         if ( m_bLastPass )
  189.             break;
  190.  
  191.     } //infinite for (outpass)
  192.  
  193.     cf.Close();
  194.     cfo.Close();
  195.     return TRUE;
  196.  
  197. }
  198.  
  199. BOOL CDcm::DecodeRec41( CGenFile& cf )
  200. {
  201.     #ifdef _DCM_DUMP_
  202.     printf( "dec41: %08lX\n", cf.Tell() - 1 );
  203.     #endif
  204.  
  205.     int iOffset = cf.readb();
  206.     BYTE* pbt = m_abtCurrBuff + iOffset;
  207.  
  208.     do
  209.     {
  210.         *( pbt-- ) = cf.readb();
  211.     } while( iOffset-- );
  212.  
  213.     return TRUE;
  214. }
  215.  
  216. BOOL CDcm::DecodeRec42( CGenFile& cf )
  217. {
  218.     #ifdef _DCM_DUMP_
  219.     printf( "dec42: %08lX\n", cf.Tell() - 1 );
  220.     #endif
  221.  
  222.     sprintf( m_szLastError, "DCM: Record type 0x42 untested. Uncomment?" );
  223.     return FALSE;
  224.  
  225.     //TODO: uncomment later!
  226.     //cf.Read( m_abtCurrBuff + 123, 5 );
  227.     //memset( m_abtCurrBuff, m_abtCurrBuff[ 123 ], 123 );
  228.     //return TRUE;
  229. }
  230.  
  231. BOOL CDcm::DecodeRec43( CGenFile& cf )
  232. {
  233.     #ifdef _DCM_DUMP_
  234.     printf( "dec43: %08lX\n", cf.Tell() - 1 );
  235.     #endif
  236.  
  237.     BYTE* pbtP = m_abtCurrBuff;
  238.     BYTE* pbtE;
  239.  
  240.     BYTE* pbtEnd = m_abtCurrBuff + m_iSectorSize;
  241.  
  242.     do
  243.     {
  244.         //uncompressed string
  245.         if ( pbtP != m_abtCurrBuff )
  246.             pbtE = m_abtCurrBuff + ReadOffset( cf );
  247.         else
  248.             pbtE = m_abtCurrBuff + cf.readb();
  249.  
  250.         if ( pbtE < pbtP )
  251.             return FALSE;
  252.  
  253.         #ifdef _DCM_DUMP_
  254.         printf( "dec43: uncst: %p %p %ld\n", pbtP, pbtE, pbtE - pbtP );
  255.         #endif
  256.  
  257.         if ( pbtE != pbtP )
  258.         {
  259.             cf.Read( pbtP, pbtE - pbtP );
  260.             pbtP = pbtE;
  261.         }
  262.  
  263.         if ( pbtP >= pbtEnd )
  264.             break;
  265.  
  266.         //rle compressed string
  267.         pbtE = m_abtCurrBuff + ReadOffset( cf );
  268.         BYTE c = cf.readb();
  269.  
  270.         #ifdef _DCM_DUMP_
  271.         printf( "dec43:   cst: %p %p %ld\n", pbtP, pbtE, pbtE - pbtP );
  272.         #endif
  273.  
  274.         if ( pbtE < pbtP )
  275.             return FALSE;
  276.  
  277.         memset( pbtP, c, pbtE - pbtP );
  278.         pbtP = pbtE;
  279.  
  280.     } while( pbtP < pbtEnd );
  281.  
  282.     return TRUE;
  283. }
  284.  
  285. BOOL CDcm::DecodeRec44( CGenFile& cf )
  286. {
  287.     #ifdef _DCM_DUMP_
  288.     printf( "dec44: %08lX\n", cf.Tell() - 1 );
  289.     #endif
  290.  
  291.     int iOffset = ReadOffset( cf );
  292.  
  293.     cf.Read( m_abtCurrBuff + iOffset, m_iSectorSize - iOffset );
  294.  
  295.     return TRUE;
  296. }
  297.  
  298. BOOL CDcm::DecodeRec46( CGenFile& cf )
  299. {
  300.     #ifdef _DCM_DUMP_
  301.     printf( "dec46: %08lX\n", cf.Tell() - 1 );
  302.     #endif
  303.  
  304.     return TRUE;
  305. }
  306.  
  307. BOOL CDcm::DecodeRec47( CGenFile& cf )
  308. {
  309.     #ifdef _DCM_DUMP_
  310.     printf( "dec47: %08lX\n", cf.Tell() - 1 );
  311.     #endif
  312.  
  313.     //TODO: Is this TRUE or NOT???
  314.     //cf.Read( m_abtCurrBuff, ( m_wCurrentSector < 4 ? 128 : m_iSectorSize ) );
  315.  
  316.     cf.Read( m_abtCurrBuff, m_iSectorSize );
  317.     return TRUE;
  318. }
  319.  
  320. BOOL CDcm::DecodeRecFA( CGenFile& cf )
  321. {
  322.     #ifdef _DCM_DUMP_
  323.     printf( "decFA: %08lX\n", cf.Tell() - 1 );
  324.     #endif
  325.  
  326.     BYTE btPom = cf.readb();
  327.  
  328.     BYTE btDensity = ( btPom >> 5 ) & 0x03;
  329.     //BYTE btPass = btPom & 0x1F;
  330.     m_bLastPass = ( btPom & 0x80 ) ? TRUE : FALSE;
  331.  
  332.     int iSpT;
  333.     int iTracks;
  334.  
  335.     switch( btDensity )
  336.     {
  337.         case DCM_DENSITY_SD:
  338.             iTracks = 40;
  339.             iSpT = 18;
  340.             m_iSectorSize = 128;
  341.             break;
  342.  
  343.         case DCM_DENSITY_DD:
  344.             iTracks = 40;
  345.             iSpT = 18;
  346.             m_iSectorSize = 256;
  347.             break;
  348.  
  349.         case DCM_DENSITY_ED:
  350.             iTracks = 40;
  351.             iSpT = 26;
  352.             m_iSectorSize = 128;
  353.             break;
  354.  
  355.         default:
  356.             sprintf( m_szLastError,"DCM: Density type unknown (%02X)\n", btDensity );
  357.             return FALSE;
  358.     }
  359.  
  360.     if ( !m_bAlreadyFormatted )
  361.     {
  362.         DISK_GEOMETRY dg;
  363.         dg.iSides = 1;
  364.         dg.iTracks = iTracks;
  365.         dg.iSectorsPerTrack = iSpT;
  366.         dg.iBytesPerSector = m_iSectorSize;
  367.  
  368.         if ( !Format( &dg ) )
  369.             return FALSE;
  370.  
  371.         m_bAlreadyFormatted = TRUE;
  372.     }
  373.     
  374.     m_wCurrentSector = cf.readLEw();
  375.  
  376.     return TRUE;
  377. }
  378.  
  379. WORD CDcm::ReadOffset( CGenFile& cf )
  380. {
  381.     BYTE bt = cf.readb();
  382.  
  383.     return( bt ? bt : 256 );
  384. }
  385.  
  386. #ifdef __CDISK_WRITE__
  387.  
  388. BOOL CDcm::Save( char* szOutFile, BOOL bOverWrite )
  389. {
  390.     if ( !bOverWrite && !access( szOutFile, F_OK ) )
  391.     {
  392.         sprintf( m_szLastError, "DCM: File already exists! '%s'", szOutFile );
  393.         return FALSE;
  394.     }
  395.  
  396.     int iDensity = -1;
  397.     m_iSectorSize = m_geometry.iBytesPerSector;
  398.  
  399.     if ( m_iSectorSize == 0x80 )
  400.     {
  401.         if ( m_geometry.iTracks == 40 )
  402.         {
  403.             if ( m_geometry.iSectorsPerTrack == 18 )
  404.                 iDensity = DCM_DENSITY_SD;
  405.  
  406.             if ( m_geometry.iSectorsPerTrack == 26 )
  407.                 iDensity = DCM_DENSITY_ED;
  408.         }
  409.     }
  410.     
  411.     if ( m_iSectorSize == 0x100 )
  412.     {
  413.         if ( ( m_geometry.iSectorsPerTrack == 18 ) &&
  414.             ( m_geometry.iTracks == 40 ) )
  415.             iDensity = DCM_DENSITY_DD;
  416.     }
  417.     
  418.     if ( iDensity == - 1 )
  419.     {
  420.         sprintf( m_szLastError, "DCM: Can't work with such density!" );
  421.         return FALSE;
  422.     }
  423.  
  424.     int iPass = 1;
  425.  
  426.     m_pbtPass = new BYTE [ 0x6500 ];
  427.  
  428.     CFile cf;
  429.  
  430.     if ( !cf.Create( szOutFile ) )
  431.     {
  432.         sprintf( m_szLastError, "DCM: Can't create '%s'", szOutFile );
  433.         delete [] m_pbtPass;
  434.         return FALSE;
  435.     }
  436.  
  437.     int iFirstSector = 0;
  438.     int iPrevSector = 0;
  439.     int iCurrentSector = 1;
  440.  
  441.     memset( m_abtPrevBuff, 0, m_iSectorSize );
  442.  
  443.     EncodeRecFA( FALSE, iPass, iDensity, iFirstSector );
  444.  
  445.     //here should be other compression
  446.  
  447.     while( iCurrentSector <= m_geometry.iSectors )
  448.     {
  449.         iFirstSector = 0;
  450.  
  451.         while( ( m_pbtCurr - m_pbtPass ) < 0x5EFD )
  452.         {
  453.             if ( iCurrentSector > m_geometry.iSectors )
  454.                 break;
  455.  
  456.             ReadSector( m_abtCurrBuff, iCurrentSector );
  457.  
  458.             BOOL bSkip = IsBlockEmpty( m_abtCurrBuff, m_iSectorSize );
  459.  
  460.             //first non empty sector is marked as first, what a surprise! :)
  461.             if ( !bSkip && !iFirstSector )
  462.             {
  463.                 iFirstSector = iCurrentSector;
  464.                 iPrevSector = iCurrentSector;
  465.             }
  466.  
  467.             //if just skipped, increment sector
  468.             if ( bSkip )
  469.             {
  470.                 iCurrentSector++;
  471.             }
  472.             else
  473.             {
  474.                 //if there is a gap, write sector number
  475.                 if ( ( iCurrentSector - iPrevSector ) > 1 )
  476.                 {
  477.                     *( m_pbtCurr++ ) = iCurrentSector;
  478.                     *( m_pbtCurr++ ) = iCurrentSector >> 8;
  479.                 }
  480.                 else
  481.                 {
  482.                     //else mark previous record
  483.                     *m_pbtLastRec |= 0x80;
  484.                 }
  485.  
  486.                 //first sector could be encoded with only some data
  487.                 if ( iCurrentSector == iFirstSector )
  488.                     EncodeRec( TRUE );
  489.                 else
  490.                 {
  491.                     //if are same, encode as record 46
  492.                     if ( !memcmp( m_abtPrevBuff, m_abtCurrBuff, m_iSectorSize ) )
  493.                         EncodeRec46();
  494.                     else
  495.                         EncodeRec( FALSE );
  496.                 }
  497.  
  498.                 //store this sector as previous
  499.                 memcpy( m_abtPrevBuff, m_abtCurrBuff, m_iSectorSize );
  500.  
  501.                 //and move pointers
  502.                 iPrevSector = iCurrentSector;
  503.                 iCurrentSector++;
  504.             }
  505.  
  506.         }
  507.  
  508.         //mark previous sector
  509.         *m_pbtLastRec |= 0x80;
  510.  
  511.         //encode end
  512.         EncodeRec45();
  513.  
  514.         BYTE* pEnd = m_pbtCurr;
  515.  
  516.         //change beginning block
  517.         if ( iCurrentSector > m_geometry.iSectors )
  518.             EncodeRecFA( TRUE, iPass, iDensity, iFirstSector );
  519.         else
  520.             EncodeRecFA( FALSE, iPass, iDensity, iFirstSector );
  521.  
  522.         //and write whole pass
  523.  
  524.         if ( ( pEnd - m_pbtPass ) > 0x6000 )
  525.         {
  526.             sprintf( m_szLastError, "DCM: Internal error! Pass too long!" );
  527.             delete [] m_pbtPass;
  528.             cf.Close();
  529.             unlink( szOutFile );
  530.             return FALSE;
  531.         }
  532.  
  533.         if ( !cf.Write( m_pbtPass, pEnd - m_pbtPass ) )
  534.         {
  535.             sprintf( m_szLastError, "DCM: Can't write!" );
  536.             delete [] m_pbtPass;
  537.             cf.Close();
  538.             unlink( szOutFile );
  539.             return FALSE;
  540.         }
  541.  
  542.         iPass++;
  543.     }
  544.  
  545.     cf.Close();
  546.  
  547.     delete [] m_pbtPass;
  548.  
  549.     return TRUE;
  550. }
  551.  
  552. void CDcm::EncodeRecFA( BOOL bLast, int iPass, int iDensity, int iFirstSec )
  553. {
  554.     m_pbtCurr = m_pbtPass;
  555.     
  556.     #ifdef _DCM_DUMP_
  557.     printf( "ERFA: %08lX\n", m_pbtCurr - m_pbtPass );
  558.     #endif
  559.  
  560.     m_pbtLastRec = m_pbtCurr;
  561.  
  562.     BYTE btType = bLast ? 0x80 : 0;
  563.  
  564.     btType |= ( iDensity & 3 ) << 5;
  565.  
  566.     btType |= ( iPass & 0x1F );
  567.  
  568.     *( m_pbtCurr++ ) = DCM_HEADER_SINGLE;
  569.     *( m_pbtCurr++ ) = btType;
  570.     *( m_pbtCurr++ ) = iFirstSec;
  571.     *( m_pbtCurr++ ) = iFirstSec >> 8;
  572.  
  573. }
  574.  
  575. void CDcm::EncodeRec45()
  576. {
  577.     #ifdef _DCM_DUMP_
  578.     printf( "ER45: %08lX\n", m_pbtCurr - m_pbtPass );
  579.     #endif
  580.  
  581.     m_pbtLastRec = m_pbtCurr;
  582.     *( m_pbtCurr++ ) = DCM_PASS_END;
  583. }
  584.  
  585. void CDcm::EncodeRec46()
  586. {
  587.     #ifdef _DCM_DUMP_
  588.     printf( "ER46: %08lX\n", m_pbtCurr - m_pbtPass );
  589.     #endif
  590.     
  591.     m_pbtLastRec = m_pbtCurr;
  592.     *( m_pbtCurr++ ) = DCM_SAME_AS_BEFORE;
  593. }
  594.  
  595. void CDcm::EncodeRec( BOOL bIsFirstSector )
  596. {
  597.     #ifdef _DCM_DUMP_
  598.     printf( "ER: %08lX\n", m_pbtCurr - m_pbtPass );
  599.     #endif
  600.     
  601.     m_pbtLastRec = m_pbtCurr;
  602.  
  603.     BYTE abtBuff41[ 0x300 ];
  604.     BYTE abtBuff43[ 0x300 ];
  605.     BYTE abtBuff44[ 0x300 ];
  606.     BYTE* abtBuff47 = m_abtCurrBuff;
  607.  
  608.     int iEnd41 = 0x300;
  609.     int iEnd43 = 0x300;
  610.     int iEnd44 = 0x300;
  611.  
  612.     int iBestMethod = DCM_UNCOMPRESSED;
  613.     int iBestEnd = m_iSectorSize;
  614.     BYTE* pbtBest = abtBuff47;
  615.  
  616.     EncodeRec43( abtBuff43, &iEnd43, m_abtCurrBuff, m_iSectorSize );
  617.  
  618.     if ( !bIsFirstSector )
  619.     {
  620.         EncodeRec41( abtBuff41, &iEnd41, m_abtCurrBuff, m_abtPrevBuff, m_iSectorSize );
  621.         EncodeRec44( abtBuff44, &iEnd44, m_abtCurrBuff, m_abtPrevBuff, m_iSectorSize );
  622.     }
  623.  
  624.     if ( iEnd41 < iBestEnd )
  625.     {
  626.         iBestMethod = DCM_CHANGE_BEGIN;
  627.         iBestEnd = iEnd41;
  628.         pbtBest = abtBuff41;
  629.     }
  630.  
  631.     if ( iEnd43 < iBestEnd )
  632.     {
  633.         iBestMethod = DCM_COMPRESSED;
  634.         iBestEnd = iEnd43;
  635.         pbtBest = abtBuff43;
  636.     }
  637.  
  638.     if ( iEnd44 < iBestEnd )
  639.     {
  640.         iBestMethod = DCM_CHANGE_END;
  641.         iBestEnd = iEnd44;
  642.         pbtBest = abtBuff44;
  643.     }
  644.  
  645.     *( m_pbtCurr++ ) = iBestMethod;
  646.     memcpy( m_pbtCurr, pbtBest, iBestEnd );
  647.     m_pbtCurr += iBestEnd;
  648. }
  649.  
  650. void CDcm::EncodeRec41( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, BYTE* pbtSrcOld, int iSrcLen )
  651. {
  652.     BYTE* pbtS = pbtSrc + iSrcLen - 1;
  653.     pbtSrcOld += iSrcLen - 1;
  654.  
  655.     BYTE* pbtD = pbtDest;
  656.  
  657.     for( int i = 0; i < iSrcLen; i++ )
  658.     {
  659.         if ( *( pbtS-- ) != * ( pbtSrcOld-- ) )
  660.             break;
  661.     }
  662.  
  663.     pbtS++;
  664.  
  665.     *( pbtD++ ) = pbtS - pbtSrc;
  666.  
  667.     int iBytes = pbtS - pbtSrc + 1;
  668.  
  669.     while( iBytes-- )
  670.     {
  671.         *( pbtD++ ) = *( pbtS-- );
  672.     }
  673.  
  674.     *piDestLen = pbtD - pbtDest;
  675. }
  676.  
  677. void CDcm::EncodeRec43( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, int iSrcLen )
  678. {
  679.     BYTE* pbtEnd = pbtSrc + iSrcLen;
  680.     BYTE* pbtCur = pbtSrc;
  681.  
  682.     BYTE* pbtD = pbtDest;
  683.  
  684.     while( pbtCur < pbtEnd )
  685.     {
  686.         BOOL bFound = FALSE;
  687.  
  688.         for( BYTE* pbtNow = pbtCur; pbtNow < ( pbtEnd - 2 ); pbtNow++ )
  689.         {
  690.  
  691.             if ( ( *pbtNow == *(pbtNow+1) ) && ( *pbtNow == *(pbtNow+2) ) )
  692.             {
  693.                 int iUnc = pbtNow - pbtCur;
  694.                 
  695.                 *( pbtD ++ ) = pbtNow - pbtSrc;
  696.                 if ( iUnc )
  697.                 {
  698.                     memcpy( pbtD, pbtCur, iUnc );
  699.                     pbtD += iUnc;
  700.                 }
  701.  
  702.                 BYTE bt = *pbtNow;
  703.                 BYTE*p;
  704.                 for( p = pbtNow + 1; p < pbtEnd; p++ )
  705.                 {
  706.                     if ( *p != bt )
  707.                         break;
  708.                 }
  709.  
  710.                 if ( p > pbtEnd )
  711.                     p = pbtEnd;
  712.  
  713.                 *( pbtD++ ) = p - pbtSrc;
  714.                 *( pbtD++ ) = bt;
  715.  
  716.                 pbtCur = p;
  717.                 bFound = TRUE;
  718.                 break;
  719.             }
  720.         }
  721.  
  722.         if ( ( pbtCur >= pbtEnd - 2 ) || !bFound ) 
  723.         {
  724.             if ( pbtCur < pbtEnd )
  725.             {
  726.                 *( pbtD++ ) = iSrcLen;
  727.                 memcpy( pbtD, pbtCur, pbtEnd - pbtCur );
  728.                 pbtD += pbtEnd - pbtCur;
  729.             }
  730.  
  731.             break;
  732.         }
  733.  
  734.     }
  735.  
  736.     *piDestLen = pbtD - pbtDest;
  737. }
  738.  
  739. void CDcm::EncodeRec44( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, BYTE* pbtSrcOld, int iSrcLen )
  740. {
  741.     BYTE* pbtS = pbtSrc;
  742.     BYTE* pbtEnd = pbtSrc + iSrcLen;
  743.  
  744.     BYTE* pbtD = pbtDest;
  745.  
  746.     for( int i = 0; i < iSrcLen; i++ )
  747.     {
  748.         if ( *( pbtS++ ) != * ( pbtSrcOld++ ) )
  749.             break;
  750.     }
  751.  
  752.     pbtS--;
  753.  
  754.     *( pbtD++ ) = pbtS - pbtSrc;
  755.     memcpy( pbtD, pbtS, pbtEnd - pbtS );
  756.     pbtD += pbtEnd - pbtS;
  757.  
  758.     *piDestLen = pbtD - pbtDest;
  759. }
  760.  
  761. #endif __CDISK_WRITE__
  762.  
  763.